package com.seed.core;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.mybatisflex.core.row.Row;
import com.seed.core.enumeration.Direction;
import com.seed.core.pojo.SetDTO;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

public class RequestWrapper {
    private final HttpServletRequest request;

    public RequestWrapper(HttpServletRequest request) {
        this.request = request;
    }

    public String getURI() {
        return request.getRequestURI();
    }

    public RequestMethod getMethod() {
        return RequestMethod.valueOf(request.getMethod());
    }

    public Integer getInt(String name, Integer defaultVal) {
        String value = request.getParameter(name);
        return StrUtil.isBlank(value) ? defaultVal : Integer.valueOf(value);
    }

    public String get(String name) {
        return request.getParameter(name);
    }

    public String get(String name, String defaultVal) {
        String value = request.getParameter(name);
        return StrUtil.isBlank(value) ? defaultVal: value;
    }

    public Row getRow() {
        try {
            String json = request.getReader().lines().collect(Collectors.joining());
            return JSONUtil.toBean(json, Row.class);
        } catch (IOException e) {
            throw new RuntimeException("获取数据异常", e);
        }
    }

    public List<Row> getRows() {
        try {
            String json = request.getReader().lines().collect(Collectors.joining());
            return JSONUtil.toList(json, Row.class);
        } catch (IOException e) {
            throw new RuntimeException("获取数据异常", e);
        }
    }

    public List<Serializable> getIds() {
        throw new RuntimeException("TODO");
    }

    public SetDTO getSetDTO() {
        throw new RuntimeException("TODO");
    }

    public List<SetDTO> getSetDTOs() {
        throw new RuntimeException("TODO");
    }

//    public <T> T readRequestBody(Class<T> clazz) {
//        try {
//            String json = request.getReader().lines().collect(Collectors.joining());
//            return JSONUtil.toBean(json, clazz);
//        } catch (IOException e) {
//            throw new RuntimeException("获取数据异常", e);
//        }
//    }

    public HttpStatus getStatus() {
        Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        if (statusCode == null) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
        try {
            return HttpStatus.valueOf(statusCode);
        }
        catch (Exception ex) {
            return HttpStatus.INTERNAL_SERVER_ERROR;
        }
    }

    public Map<String, String> getSearch() {
        return getSearchStartingWith("search_");
    }

    public Map<String, Direction> getOrder() {
        return getOrderStartingWith("order_");
    }

    public String getKeyword() {
        return request.getParameter("keyword");
    }

    public List<List<String>> getDataPermis() {
        return Collections.emptyList();
    }

    public LinkedHashMap<String, String> getFieldPermis() {
        LinkedHashMap<String, String> ret = new LinkedHashMap<>();
        ret.put("name", "=加1");

        return ret;
    }

//    public String getSeedName() {
//        return (String) request.getAttribute("seedName");
//    }
//
//    public String getActionName() {
//        return (String) request.getAttribute("actionName");
//    }


    /**
     * 取得带相同前缀的Request Parameters, copy from spring WebUtils.
     *
     * 返回的结果的Parameter名已去除前缀.
     */
    private Map<String, String> getSearchStartingWith(String prefix) {
        Enumeration<String> paramNames = request.getParameterNames();
        Map<String, String> ret = new HashMap<>();
        if (prefix == null) prefix = "";

        while ((paramNames != null) && paramNames.hasMoreElements()) {
            String paramName = paramNames.nextElement();
            if ("".equals(prefix) || paramName.startsWith(prefix)) {
                String unprefixed = paramName.substring(prefix.length());
                String[] values = request.getParameterValues(paramName);
                if ((values == null) || (values.length == 0)) {
                    // Do nothing, no values found at all.
                } else if (values.length > 1) {
                    ret.put(unprefixed, StrUtil.join(",", List.of(values)));
                } else {
                    ret.put(unprefixed, values[0]);
                }
            }
        }

        return ret;
    }

    private Map<String, Direction> getOrderStartingWith(String prefix) {
        Enumeration<String> paramNames = request.getParameterNames();
        Map<String, Direction> ret = new HashMap<>();
        if (prefix == null) prefix = "";

        while ((paramNames != null) && paramNames.hasMoreElements()) {
            String paramName = paramNames.nextElement();
            if ("".equals(prefix) || paramName.startsWith(prefix)) {
                String unprefixed = paramName.substring(prefix.length());
                String[] values = request.getParameterValues(paramName);
                if ((values == null) || (values.length == 0)) {
                    ret.put(unprefixed, Direction.asc);
                } else {
                    ret.put(unprefixed, Direction.valueFrom(values[0]));
                }
            }
        }

        return ret;
    }

    public void forward(String path, HttpServletResponse response) {
        try {
            request.getRequestDispatcher(path).forward(request, response);
        } catch (ServletException | IOException e) {
            throw new RuntimeException(e);
        }
    }
}
